#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include "stp.h"

MODULE_DESCRIPTION("SO2 Transport Protocol implementation");
MODULE_AUTHOR("Victor Buciuc");
MODULE_LICENSE("GPL");

/*
 * stp structures
 */

struct stp_sock {
	struct sock 	sk;

	be16		stp_src;
	int		sas_ifindex;
	be16		stp_dst;
	u8		stp_addr[6];
};


static struct proto stp_prot = {
	.name		= "PACKET",
	.owner		= THIS_MODULE,
	.obj_size	= sizeof(struct stp_sock),
};

static struct net_proto_family stp_family_ops = {
	.family		= PF_STP,
	.create		= stp_create,
	.owner		= THIS_MODULE,
};

/*
 * Create a socket. Only accept type datagram.
 */
static int packet_create(struct net *net, struct socket *sock, int protocol,
			 int kern)
{
	struct sock 	*sk;
	int		err;
	
	if (sock->type != SOCK_DGRAM) {
		return -ESOCKTNOSUPPORT;
	}

	/*
	 * opt TODO. setup protocol slab for packet headers
	 */
	err = -ENOBUFS;
	sk = sk_alloc(net, PF_STP, GFP_KERNEL, &stp_prot);
	if (sk == NULL)
		goto err;

	sock_init_data(sock, sk);
	sock->ops = &stp_ops;

	sk->sk_destruct = stp_sock_destruct;
	sk->sk_protocol = PF_STP;

	sk_refcnt_debug_inc(sk);

	return 0;
err:
	return err;
}

/*
 * Initialisation stuff
 */
static int stp_init(void)
{
	int rc;
	printk( KERN_DEBUG "STP:Registering protocol\n" );

	rc = proto_register(&packet_proto, 0);

	if (rc != 0)
		goto out;

out:	
	return rc;
}

static void stp_exit(void)
{
	printk( KERN_DEBUG "Bye\n" );
}

module_init(stp_init);
module_exit(stp_exit);
